/* -----------------------------------------------------------------------
 * Paul Cohen
 * CS 362, Summer 2014
 * Assignment 4
 *
 * randomtestadventurer.c - random tester for Dominion's Adventurer card
 *
 * -----------------------------------------------------------------------
 */

#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define NUM_TESTS 10000

int main(int argc, char const *argv[])
{
    int i, j, numPlayers = 0, currentPlayer = 0;
    int deckCount = 0, handCount = 0, discardCount = 0;
    int currentCard = 0, treasureBefore = 0, treasureAfter = 0;
    struct gameState G;

    SelectStream(2);
    PutSeed(time(NULL));

    for (i = 0; i < NUM_TESTS; i++)
    {
        // initialize/reset
        memset(&G, 0, sizeof(struct gameState));
        for (j = 0; j < sizeof(struct gameState); j++) {
          ((char*)&G)[j] = floor(Random() * 256);
        }
        treasureBefore = 0, treasureAfter = 0;

        // randomize current player and number of cards in deck, hand, and discard pile
        numPlayers = floor(Random() * 3) + 2;
        currentPlayer = floor(Random() * numPlayers);
        deckCount = floor(Random() * MAX_DECK) + 1;
        handCount = floor(Random() * MAX_HAND) + 1;
        discardCount = floor(Random() * MAX_DECK) + 1;
        G.whoseTurn = currentPlayer;
        G.deckCount[currentPlayer] = deckCount;
        G.handCount[currentPlayer] = handCount;
        G.discardCount[currentPlayer] = discardCount;

        // fill deck with random cards
        for (j = 0; j < deckCount; j++)
        {
            G.deck[currentPlayer][j] = floor(Random() * 26);
        }
        // fill hand with random cards and count treasures
        for (j = 0; j < handCount; j++)
        {
            G.hand[currentPlayer][j] = floor(Random() * 26);
            currentCard = G.hand[currentPlayer][j];
            if (currentCard == copper || currentCard == silver || currentCard == gold)
                treasureBefore++;
        }

        // run Adventurer Card function
        cardEffect(adventurer, 0, 0, 0, &G, 0, 0);

        // count treasures in new hand
        for (j = 0; j < G.handCount[currentPlayer]; j++)
        {
            currentCard = G.hand[currentPlayer][j];
            if (currentCard == copper || currentCard == silver || currentCard == gold)
                treasureAfter++;
        }

        // test for correct amount of treasures in hand
        if (!(treasureAfter == (treasureBefore + 2)))
        {
            printf("(Iteration %d) ERROR 1: treasure count is incorrect.\n", i);
            printf("Details:\n");
            printf("Number of players: %d\tCurrent player: %d\n", numPlayers, currentPlayer + 1);
            printf("Before Function:\tdeck count: %d, hand count: %d, discard count: %d, treasure count: %d\n", deckCount, handCount, discardCount, treasureBefore);
            printf("After Function:\t\tdeck count: %d, hand count: %d, discard count: %d, treasure count: %d\n", G.deckCount[currentPlayer], G.handCount[currentPlayer], G.discardCount[currentPlayer], treasureAfter);
            printf("------------\n");
        }

        // test for correct amount of cards in discard pile
        if (!(G.discardCount[currentPlayer] == discardCount + (deckCount - G.deckCount[currentPlayer] - (treasureAfter - treasureBefore))))
        {
            printf("(Iteration %d) ERROR 2: incorrect number of cards discarded.\n", i);
            printf("Details:\n");
            printf("Number of players: %d\tCurrent player: %d\n", numPlayers, currentPlayer + 1);
            printf("Before Function:\tdeck count: %d, hand count: %d, discard count: %d, treasure count: %d\n", deckCount, handCount, discardCount, treasureBefore);
            printf("After Function:\t\tdeck count: %d, hand count: %d, discard count: %d, treasure count: %d\n", G.deckCount[currentPlayer], G.handCount[currentPlayer], G.discardCount[currentPlayer], treasureAfter);
            printf("------------\n");
        }
    }

    return 0;
}
